/* syscall.c : syscalls
 */

#include <xeroskernel.h>
#include <stdarg.h>


int syscall( int req, ... ) {
/**********************************/

    va_list     ap;
    int         rc;

    va_start( ap, req );

    __asm __volatile( " \
        movl %1, %%eax \n\
        movl %2, %%edx \n\
        int  %3 \n\
        movl %%eax, %0 \n\
        "
        : "=g" (rc)
        : "g" (req), "g" (ap), "i" (SYSCALL_INT)
        : "%eax" 
    );
 
    va_end( ap );

    return( rc );
}

 int syscreate( funcptr fp, int stack ) {
/*********************************************/

    return( syscall( SYS_CREATE, fp, stack ) );
}

 int sysyield( void ) {
/***************************/

    return( syscall( SYS_YIELD ) );
}

 int sysstop( void ) {
/**************************/
    return( syscall( SYS_STOP ) );
}

extern unsigned int sysgetpid(void){
	//system call to get pid of running process 
	return( syscall(SYS_GET_PID) );
}

extern void sysputs(char *str){
	//system call to print str
	syscall(SYS_PUT,str);
}

extern int syssend(unsigned int dest_pid, void *buffer, int buffer_len){
	//system call for send() in msg.c
	return(syscall(SYS_SEND, dest_pid, buffer, buffer_len));
}

extern int sysrecv(unsigned int *from_pid, void *buffer, int buffer_len){
	//system call for recv() in msg.c
	return(syscall(SYS_RECV,from_pid, buffer, buffer_len));
}

unsigned int syssleep(unsigned int milliseconds) {
    syscall(SYS_SLEEP, milliseconds);
    return 0;
}

extern int sysopen(int device_no){
	return syscall(SYS_OPEN, device_no);
}

extern int sysclose(int fd){
	return syscall(SYS_CLOSE, fd);
}

extern int syswrite(int fd, void *buff, int bufflen){
	return syscall(SYS_WRITE, fd, buff, bufflen);
}

extern int sysread(int fd, void *buff, int bufflen){
	return syscall(SYS_READ, fd, buff, bufflen);
}

extern int sysioctl(int fd, unsigned long command, ...){
	void *args = &command+1;
	return syscall(SYS_IOCTL, fd, command, args);
}

int syssighandler(int sig, void (*newHandler)(void *), void (** oldHandler)(void *)){
    //function installs a signal it'll register a signal number
    return( syscall( SYS_SIGHANDLER, sig, newHandler, oldHandler ) );
}

int syskill(int pid, int signum) {
    //request signal deliverance
    return( syscall( SYS_SIGNAL, pid, signum ) );
}

int syssigwait() {
    //wait for signal, do the signal, then come back here with which signal went off
    return(syscall(SYS_SIGWAIT));
}

void sigreturn(void *old_sp) {
    syscall( SYS_SIGRETURN, old_sp );
}
